package com.ruoyi.common.utils;

import java.io.File;
import java.net.NetworkInterface;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import com.alibaba.fastjson.JSON;
import com.ruoyi.common.utils.file.FileUtils;

public class LicenseUtil {
	
	private static String getMac() {
	  try {
	      Enumeration<NetworkInterface> el = NetworkInterface.getNetworkInterfaces();
	      while (el.hasMoreElements()) {
	          byte[] mac = el.nextElement().getHardwareAddress();
	          if (mac == null)
	              continue;
	          String hexstr = bytesToHexString(mac);
	          
	          return hexstr.toUpperCase();
	      }
	  } catch (Exception exception) {
	      exception.printStackTrace();
	  }
	  return null;
	}
	
	public static String getMachineCode(String salt) {
    Set<String> result = new HashSet<>();
    String mac = getMac();
    result.add(mac);
    Properties props = System.getProperties();
    String javaVersion = props.getProperty("java.version");
    result.add(javaVersion);
    String javaVMVersion = props.getProperty("java.vm.version");
    result.add(javaVMVersion);
    String osVersion = props.getProperty("os.version");
    result.add(osVersion);

    if (StringUtils.isEmpty(salt)) {
    	salt = EncryptUtil.getSalt(EncryptUtil.PASS_NUM);
    }
    
    String code = EncryptUtil.getMd5Pass(result.toString(), salt, EncryptUtil.ITERATIONS);
    
    String str = getSplitString(code, "-", 8) + "-" + salt;
     
    return str;
	}
	
	public static boolean licenseVerify(File file) {
		
		String str = FileUtils.readFile(file);
		if (StringUtils.isEmpty(str)) {
			return false;
		}
		
    String content = EncryptUtil.convertMD5(str);
    
		Map<String,String> conMap = JSON.parseObject(content, Map.class);
		String isNoTimeLimit = conMap.get("LICENSETYPE");
		String licenseLimit = conMap.get("EXPIREDAY");
		String machineCode = conMap.get("MACHINECODE");
		String licenseSign = conMap.get("LICENSESIGN"); 
		
    String sign = getSign(isNoTimeLimit, licenseLimit, machineCode);

    String salt = machineCode.substring(machineCode.lastIndexOf("-")+1);
    
    String licenseSign2 = EncryptUtil.getMd5Pass(sign, salt, EncryptUtil.ITERATIONS);
    
    if (!StringUtils.equals(licenseSign, licenseSign2)) {
    	return false;
    }
    
    if ("0".equals(isNoTimeLimit)) {
    	Date date = DateUtils.parseDate(DateUtils.getDate());
    	Date limitDate = DateUtils.parseDate(licenseLimit);
    	if (date.after(limitDate)) {
    		return false;
    	}
    }
    
    String machineCode2 = getMachineCode(salt);
    if (!StringUtils.equals(machineCode2, machineCode)) {
    	return false;
    }
				
		return true;
	}
	
	public static String getSign(String isNoTimeLimit, String licenseLimit, String machineCode) {
		StringBuilder sign = new StringBuilder();
    sign.append("LICENSETYPE=").append(isNoTimeLimit).append("yingwei")
    	.append("EXPIREDAY=").append(licenseLimit).append("yingwei")
    	.append("MACHINECODE=").append(licenseLimit).append("yingwei");
    
    return sign.toString();
	}
	
	public static String getSplitString(String str, String regex, int limit) {
    String reg = "(.{"+limit+"})";
    str = str.replaceAll(reg, "$1"+regex);
    if (str.endsWith(regex)) {
    	return str.substring(0, str.length()-1);
    }
    return str;
	}

  public static String bytesToHexString(byte[] src){
      StringBuilder stringBuilder = new StringBuilder("");
      if (src == null || src.length <= 0) {
          return null;
      }
      for (int i = 0; i < src.length; i++) {
          int v = src[i] & 0xFF;
          String hv = Integer.toHexString(v);
          if (hv.length() < 2) {
              stringBuilder.append(0);
          }
          stringBuilder.append(hv);
      }
      return stringBuilder.toString();
  }
  
	/**
	 * @param args
	 * @throws Exception
	 */
	public static void main(String[] args) throws Exception {
		String str = getMachineCode(null);
		
//		boolean b = licenseVerify("d:/license.lic");
//		System.err.println("b="+b);
	}
}
